/**
 * 微信小程序错误处理器
 * 专门处理 32776、32774 等视图更新错误
 */

class WechatErrorHandler {
  constructor() {
    this.errorCounts = new Map()
    this.maxErrorCount = 5
    this.errorCooldown = 5000 // 5秒冷却时间
    this.lastErrorTime = new Map()
    this._initialized = false
    
    this.init()
  }

  init() {
    // 避免重复初始化
    if (this._initialized) return
    this._initialized = true
    
    // 监听全局错误
    if (typeof wx !== 'undefined' && wx.onError) {
      wx.onError = (error) => {
        this.handleWechatError(error)
      }
    }

    // 监听 unhandledrejection
    if (typeof wx !== 'undefined' && wx.onUnhandledRejection) {
      wx.onUnhandledRejection((res) => {
        this.handleUnhandledRejection(res)
      })
    }
  }

  /**
   * 处理微信小程序错误
   * @param {string|Error} error - 错误信息
   */
  handleWechatError(error) {
    const errorStr = typeof error === 'string' ? error : error.message || error.toString()
    
    // 忽略函数定义被当作错误的情况
    if (errorStr.includes('function (error)') || errorStr.includes('function(error)')) {
      return
    }
    
    // 检查是否是视图更新相关错误
    if (this.isViewUpdateError(errorStr)) {
      this.handleViewUpdateError(errorStr)
    }
    
    // 记录错误
    console.error('微信小程序错误:', errorStr)
  }

  /**
   * 处理未捕获的 Promise 拒绝
   * @param {Object} res - 拒绝信息
   */
  handleUnhandledRejection(res) {
    const error = res.reason || res.promise
    console.error('未处理的 Promise 拒绝:', error)
    
    if (typeof error === 'string' && this.isViewUpdateError(error)) {
      this.handleViewUpdateError(error)
    }
  }

  /**
   * 检查是否是视图更新错误
   * @param {string} errorStr - 错误字符串
   * @returns {boolean}
   */
  isViewUpdateError(errorStr) {
    const viewUpdateErrors = [
      'insertTextView:fail',
      'updateTextView:fail',
      'insertImageView:fail',
      'updateImageView:fail',
      'not found',
      '32776',
      '32774',
      '32773',
      '32777'
    ]
    
    return viewUpdateErrors.some(pattern => errorStr.includes(pattern))
  }

  /**
   * 处理视图更新错误
   * @param {string} errorStr - 错误字符串
   */
  handleViewUpdateError(errorStr) {
    const errorType = this.getErrorType(errorStr)
    const now = Date.now()
    
    // 检查错误频率
    const lastTime = this.lastErrorTime.get(errorType) || 0
    if (now - lastTime < this.errorCooldown) {
      return // 在冷却期内，忽略重复错误
    }
    
    this.lastErrorTime.set(errorType, now)
    
    // 增加错误计数
    const count = (this.errorCounts.get(errorType) || 0) + 1
    this.errorCounts.set(errorType, count)
    
    console.warn(`视图更新错误 ${errorType} 发生 ${count} 次`)
    
    // 如果错误次数过多，采取恢复措施
    if (count >= this.maxErrorCount) {
      this.attemptRecovery(errorType)
    }
  }

  /**
   * 获取错误类型
   * @param {string} errorStr - 错误字符串
   * @returns {string}
   */
  getErrorType(errorStr) {
    if (errorStr.includes('insertTextView')) return 'INSERT_TEXT_VIEW'
    if (errorStr.includes('updateTextView')) return 'UPDATE_TEXT_VIEW'
    if (errorStr.includes('insertImageView')) return 'INSERT_IMAGE_VIEW'
    if (errorStr.includes('updateImageView')) return 'UPDATE_IMAGE_VIEW'
    return 'UNKNOWN_VIEW_ERROR'
  }

  /**
   * 尝试恢复
   * @param {string} errorType - 错误类型
   */
  attemptRecovery(errorType) {
    console.log(`尝试从 ${errorType} 错误中恢复`)
    
    // 重置错误计数
    this.errorCounts.set(errorType, 0)
    
    // 触发页面重新渲染
    try {
      // 获取当前页面
      const pages = getCurrentPages()
      const currentPage = pages[pages.length - 1]
      
      if (currentPage && typeof currentPage.setData === 'function') {
        // 强制重新渲染
        currentPage.setData({
          _forceUpdate: Date.now()
        })
      }
    } catch (recoveryError) {
      console.error('恢复失败:', recoveryError)
    }
  }

  /**
   * 清理错误统计
   */
  clearErrorStats() {
    this.errorCounts.clear()
    this.lastErrorTime.clear()
  }

  /**
   * 获取错误统计
   * @returns {Object}
   */
  getErrorStats() {
    return {
      errorCounts: Object.fromEntries(this.errorCounts),
      lastErrorTime: Object.fromEntries(this.lastErrorTime)
    }
  }
}

// 创建全局实例
const wechatErrorHandler = new WechatErrorHandler()

export default wechatErrorHandler